package com.climb.moive.framework.jdbc;

import com.climb.moive.util.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class JdbcTemplate {
    private Connection con;

    public JdbcTemplate(Connection con) {
        this.con = con;
    }

    // 1、新增、修改和删除方法
    public int update(String sql, Object... args) throws SQLException {
        int rows = 0;
        PreparedStatement prepareStatement = null;
        try {
            // 获取数据库连接
            // 获取语句句柄
            prepareStatement = con.prepareStatement(sql);
            // 赋参数
            for(int i = 0; i < args.length; i++) {
                prepareStatement.setObject(i + 1, args[i]);
            }
            // 执行更新
            rows = prepareStatement.executeUpdate();
        } finally {
            // 释放资源
            JdbcUtils.close(prepareStatement);
        }

        return rows;
    }

    // 2、返回简单类型的方法，如Integer、String等
    public <T> T queryForObject(String sql, Class<T> requiredType, Object... args) throws SQLException {
        PreparedStatement preparedStatement = null;
        ResultSet rs = null;
        try {
            // 获得数据库连接
            // 创建语句句柄
            preparedStatement = con.prepareStatement(sql);
            // 设置参数
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            // 执行查询
            rs = preparedStatement.executeQuery();

            // 解析结果集
            // 策略模式
            if (rs.next()) {
                com.climb.moive.framework.jdbc.RowMapper<T> rowMapper = new com.climb.moive.framework.jdbc.SingleColumnRowMapper<>(requiredType);
                return rowMapper.mapRow(rs, 0);
            }

            return null;
        } finally {
            // 释放资源
            JdbcUtils.close(rs);
            JdbcUtils.close(preparedStatement);
        }
    }

    // 3、返回一个对象的方法
    public <T> T queryForObject(String sql, com.climb.moive.framework.jdbc.RowMapper<T> rowMapper, Object... args) throws SQLException {
        PreparedStatement preparedStatement = null;
        ResultSet rs = null;
        try {
            // 获得数据库连接
            // 创建语句句柄
            preparedStatement = con.prepareStatement(sql);
            // 设置参数
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            // 执行查询
            rs = preparedStatement.executeQuery();

            // 解析结果集
            // 策略模式
            if (rs.next()) {
                return rowMapper.mapRow(rs, 0);
            }

            return null;
        } finally {
            // 释放资源
            JdbcUtils.close(rs);
            JdbcUtils.close(preparedStatement);
        }
    }

    // 4、返回一个对象集合的方法
    public <T> List<T> query(String sql, com.climb.moive.framework.jdbc.RowMapper<T> rowMapper, Object... args) throws SQLException {
        PreparedStatement preparedStatement = null;
        ResultSet rs = null;
        try {
            // 获得数据库连接
            // 创建语句句柄
            preparedStatement = con.prepareStatement(sql);
            // 设置参数
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            // 执行查询
            rs = preparedStatement.executeQuery();

            // 解析结果集
            List<T> list = new ArrayList<>();
            int rowNum = 0;
            // 策略模式
            while (rs.next()) {
                T t = rowMapper.mapRow(rs, rowNum++);
                list.add(t);
            }

            return list;
        } finally {
            // 释放资源
            JdbcUtils.close(rs);
            JdbcUtils.close(preparedStatement);
        }
    }
}